﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ComicIsland.App.Resources;
using ComicIsland.Common;
using ComicIsland.Common.Entities.LocalDatabase;

/**
 * 创建时间：2015/1/11 23:01:51
 * 作者：yong.blackcore
 * Email：itblackhole@outlook.com
 * QQ：50404503
 */
namespace ComicIsland.App.Views.CacheManage
{
    public class CacheManageDBContextHelper
    {
        System.Threading.Mutex mutex = new System.Threading.Mutex(false, AppResources.ApplicationTitle);

        private CacheManageDBContext dbContext;
        public CacheManageDBContextHelper(CacheManageDBContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public void MutexThread(object obj)
        {
            try
            {
                mutex.WaitOne();
                LogHelper.LogInfo("...", this.GetType(), MethodBase.GetCurrentMethod());
                Task.Delay(100);
            }
            catch (Exception err)
            {
                LogHelper.LogInfo(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }



        #region ******************************Comic'Chapter'Image******************************
        public void InsertComicChapterImages(IEnumerable<LDBComicChapterImage> comicChapterImages)
        {
            try
            {
                this.mutex.WaitOne();
                if (comicChapterImages != null && comicChapterImages.Count() > 0)
                {
                    foreach (LDBComicChapterImage item in comicChapterImages)
                    {
                        var table = this.dbContext.GetTable<LDBComicChapterImage>();
                        if (table != null && table.Count() > 0)
                        {
                            LDBComicChapterImage currentRow = null;
                            table.Where(p => p.ComicId == item.ComicId && p.BookId == item.BookId && p.PartId == item.PartId && p.ImageUrl.Equals(item.ImageUrl)).FirstOrDefault<LDBComicChapterImage>();
                            if (currentRow == null)
                            {
                                this.dbContext.Images.InsertOnSubmit(item);
                                this.dbContext.SubmitChanges();
                            }
                        }
                        else
                        {
                            this.dbContext.Images.InsertOnSubmit(item);
                            this.dbContext.SubmitChanges();
                        }
                    }
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
        }

        public bool RemoveComicChapterImageByComicId(int comicId, int bookId)
        {
            bool result = false;
            try
            {
                mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapterImage>();
                if (table != null && table.Count() > 0)
                {
                    var items = (from p in table where p.ComicId == comicId && p.BookId == bookId select p).ToList<LDBComicChapterImage>();
                    if (items != null && items.Count > 0)
                    {
                        this.dbContext.Images.DeleteAllOnSubmit(items);
                        this.dbContext.SubmitChanges();
                    }
                }
                result = true;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
            return result;
        }

        public bool RemoveComicChapterImageByComicIdAndChapterId(int comicId, int bookId, int chapterId)
        {
            bool result = false;
            try
            {
                mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapterImage>();
                if (table != null && table.Count() > 0)
                {
                    var items = (from p in table where p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId select p).ToList<LDBComicChapterImage>();
                    if (items != null && items.Count > 0)
                    {
                        this.dbContext.Images.DeleteAllOnSubmit(items);
                        this.dbContext.SubmitChanges();
                    }
                }
                result = true;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
            return result;
        }

        public ObservableCollection<LDBComicChapterImage> GetAllComicChapterImageByComicIdAndChapterId(int comicId, int bookId, int chapterId)
        {
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapterImage>();

                if (table != null && table.Count() > 0)
                {
                    var list = table.Where(p => p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId).ToList<LDBComicChapterImage>();
                    if (list != null && list.Count > 0)
                    {
                        return new ObservableCollection<LDBComicChapterImage>(list);
                    }
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return null;
        }

        public bool IsCachedComicChapterByComicIdAndChapterId(int comicId, int bookId, int chapterId)
        {
            bool result = false;
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapterImage>();

                if (table != null && table.Count() > 0)
                {
                    var items = table.Where(p => p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId).ToList<LDBComicChapterImage>();
                    if (items != null && items.Count > 0)
                    {
                        int completedTotal = items.Where(p => ContentDownloadStatus.已完成.ToString().Equals(p.DownloadStatus)).Count();
                        if (items.Count == completedTotal)
                            result = true;
                    }
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return result;
        }

        public LDBComicChapterImage GetOneComicChapterImageByDownloadStatus(ContentDownloadStatus status, int comicId = 0, int bookId = 0)
        {
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapterImage>();
                if (table != null && table.Count() > 0)
                {
                    return table.Where(p => (comicId <= 0 ? true : p.ComicId == comicId) && (bookId <= 0 ? true : p.BookId == bookId) && p.DownloadStatus.Equals(status.ToString())).OrderBy(p => p.Id).FirstOrDefault<LDBComicChapterImage>();
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }

            return null;
        }

        public void UpdateStatusToComicChapterImage(LDBComicChapterImage dbImage, ContentDownloadStatus status)
        {
            try
            {
                this.mutex.WaitOne();
                if (dbImage == null)
                    return;
                var table = this.dbContext.GetTable<LDBComicChapterImage>();
                if (table != null && table.Count() > 0)
                {
                    var rowComicChapterImages = table.Where(p => p.ComicId == dbImage.ComicId && p.BookId == dbImage.BookId && p.PartId == dbImage.PartId && p.ImageUrl.Equals(dbImage.ImageUrl)).ToList<LDBComicChapterImage>();
                    if (rowComicChapterImages != null && rowComicChapterImages.Count > 0)
                    {
                        foreach (var row in rowComicChapterImages)
                        {
                            if (row == null)
                                continue;
                            row.DownloadStatus = status.ToString();
                            this.dbContext.SubmitChanges();
                        }
                    }
                }

                if (ContentDownloadStatus.已完成.ToString().Equals(status.ToString()))
                {
                    bool IsAllCompletedComicChapterImage = true;
                    table = this.dbContext.GetTable<LDBComicChapterImage>();

                    if (table != null && table.Count() > 0)
                    {
                        var list = table.Where(p => p.ComicId == dbImage.ComicId && p.BookId == dbImage.BookId && p.PartId == dbImage.PartId
                            && !p.DownloadStatus.Equals(ContentDownloadStatus.已完成.ToString())).ToList<LDBComicChapterImage>();
                        if (list != null && list.Count > 0)
                        {
                            IsAllCompletedComicChapterImage = false;
                        }
                    }

                    if (IsAllCompletedComicChapterImage)
                    {
                        //如果已经下载完成了，更新章节的状态
                        #region 漫画中章节的图片地址全部下载完成，更新章节状态
                        var tableComicChapter = this.dbContext.GetTable<LDBComicChapter>();
                        LDBComicChapter rowComicChapter = null;
                        if (tableComicChapter != null && tableComicChapter.Count() > 0)
                        {
                            rowComicChapter = tableComicChapter.Where(p => p.ComicId == dbImage.ComicId && p.BookId == dbImage.BookId && p.PartId == dbImage.PartId).FirstOrDefault<LDBComicChapter>();
                        }
                        if (rowComicChapter != null)
                        {
                            rowComicChapter.DownloadStatus = status.ToString();
                            this.dbContext.SubmitChanges();
                        }
                        if (ContentDownloadStatus.已完成.ToString().Equals(status.ToString()))
                        {
                            bool IsAllCompletedComicChapter = true;
                            var tmpComicChapters = table.Where(p => p.ComicId == dbImage.ComicId && p.BookId == dbImage.BookId && !p.DownloadStatus.Equals(ContentDownloadStatus.已完成)).ToList<LDBComicChapterImage>();
                            if (tmpComicChapters != null && tmpComicChapters.Count > 0)
                            {
                                IsAllCompletedComicChapter = false;
                            }

                            if (IsAllCompletedComicChapter)
                            {
                                #region 漫画中的章节全部下载完成，更新漫画下载状态
                                var tableComic = this.dbContext.GetTable<LDBComic>();
                                LDBComic rowComic = null;
                                if (tableComic != null && tableComic.Count() > 0)
                                {
                                    rowComic = tableComic.Where(p => p.ComicId == dbImage.ComicId && p.BookId == dbImage.BookId).FirstOrDefault<LDBComic>();
                                }
                                if (rowComic != null)
                                {
                                    rowComic.DownloadStatus = status.ToString();
                                    this.dbContext.SubmitChanges();
                                }
                                #endregion 漫画中的章节全部下载完成，更新漫画下载状态
                            }
                        }
                        #endregion 漫画中章节的图片地址全部下载完成，更新章节状态
                    }
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
        }
        #endregion ******************************Comic'Chapter'Image******************************



        #region ******************************Comic'Chapter******************************
        public LDBComicChapter GetOneComicChapter(int comicId, int bookId, int chapterId)
        {
            try
            {
                mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapter>();
                if (table != null && table.Count() > 0)
                {
                    return table.Where(p => p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId).FirstOrDefault<LDBComicChapter>();
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
            return null;
        }

        public LDBComicChapter GetOneComicChapterByDownloadStatus(ContentDownloadStatus status, int comicId = 0, int bookId = 0)
        {
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapter>();
                if (table != null && table.Count() > 0)
                {
                    return table.Where(p => ((comicId <= 0 ? true : p.ComicId == comicId)) && (bookId <= 0 ? true : p.BookId == bookId) && p.DownloadStatus.Equals(status.ToString())).OrderBy(p => p.PartId).FirstOrDefault<LDBComicChapter>();
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return null;
        }

        public void InsertChapter(int comicId, int bookId, IEnumerable<LDBComicChapter> chapters)
        {
            try
            {
                mutex.WaitOne();
                //
                var table = this.dbContext.GetTable<LDBComic>();
                if (table != null && table.Count() > 0)
                {
                    LDBComic ldbComic = table.Where(p => p.ComicId == comicId && p.BookId == bookId).FirstOrDefault<LDBComic>();
                    if (ldbComic != null)
                    {
                        ldbComic.DownloadStatus = ContentDownloadStatus.等待中.ToString();
                        this.dbContext.SubmitChanges();
                    }
                }
                if (chapters != null && chapters.Count() > 0)
                {
                    foreach (LDBComicChapter item in chapters)
                    {
                        this.dbContext.Chapters.InsertOnSubmit(item);
                    }
                    this.dbContext.SubmitChanges();
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }

        public bool RemoveComicChapterByComicIdAndChapterId(int comicId, int bookId, int chapterId)
        {
            bool result = false;
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapter>();
                if (table != null && table.Count() > 0)
                {
                    var items = (from p in table where p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId select p).ToList<LDBComicChapter>();
                    if (items != null && items.Count > 0)
                    {
                        this.dbContext.Chapters.DeleteAllOnSubmit(items);
                        this.dbContext.SubmitChanges();
                    }
                }
                result = true;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return result;
        }

        public bool RemoveComicChapterByComicId(int comicId,int bookId)
        {
            bool result = false;
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapter>();
                if (table != null && table.Count() > 0)
                {
                    var items = (from p in table where p.ComicId == comicId && p.BookId == bookId select p).ToList<LDBComicChapter>();
                    if (items != null && items.Count > 0)
                    {
                        this.dbContext.Chapters.DeleteAllOnSubmit(items);
                        this.dbContext.SubmitChanges();
                    }
                }
                result = true;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return result;

        }

        public ObservableCollection<LDBComicChapter> GetAllChaptersByComicId(int comicId, int bookId)
        {
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComicChapter>();
                if (table != null && table.Count() > 0)
                {
                    var list = table.Where(p => p.ComicId == comicId && p.BookId == bookId).OrderBy(p => p.PartId).ToList<LDBComicChapter>();
                    if (list != null && list.Count > 0)
                    {
                        return new ObservableCollection<LDBComicChapter>(list);
                    }
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return null;
        }

        public bool PauseComicChapterByComicIdAndChapterId(int comicId, int bookId, int chapterId)
        {
            bool result = false;
            try
            {
                this.mutex.WaitOne();
                var tableComicChapters = this.dbContext.GetTable<LDBComicChapter>();
                if (tableComicChapters != null && tableComicChapters.Count() > 0)
                {
                    var rowComicChapter = (from p in tableComicChapters where p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId select p).FirstOrDefault<LDBComicChapter>();
                    if (rowComicChapter != null)
                    {
                        rowComicChapter.DownloadStatus = ContentDownloadStatus.已暂停.ToString();
                        this.dbContext.SubmitChanges();
                        //
                        var tableComicChapterImages = this.dbContext.GetTable<LDBComicChapterImage>();
                        if (tableComicChapterImages != null && tableComicChapterImages.Count() > 0)
                        {
                            var rowComicChapterImages = (from p in tableComicChapterImages where p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId select p).ToList<LDBComicChapterImage>();
                            if (rowComicChapterImages != null && rowComicChapterImages.Count > 0)
                            {
                                foreach (LDBComicChapterImage rowCCI in rowComicChapterImages)
                                {
                                    if (ContentDownloadStatus.等待中.ToString().Equals(rowCCI.DownloadStatus))
                                    {
                                        rowCCI.DownloadStatus = ContentDownloadStatus.已暂停.ToString();
                                        this.dbContext.SubmitChanges();
                                    }
                                }
                            }
                        }
                    }
                }
                result = true;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return result;
        }

        public bool PendingComicChapterByComicIdAndChapterId(int comicId, int bookId, int chapterId)
        {
            bool result = false;
            try
            {
                this.mutex.WaitOne();
                var tableComicChapters = this.dbContext.GetTable<LDBComicChapter>();
                if (tableComicChapters != null && tableComicChapters.Count() > 0)
                {
                    var rowComicChapter = (from p in tableComicChapters where p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId select p).FirstOrDefault<LDBComicChapter>();
                    if (rowComicChapter != null)
                    {
                        rowComicChapter.DownloadStatus = ContentDownloadStatus.等待中.ToString();
                        this.dbContext.SubmitChanges();
                        //
                        var tableComicChapterImages = this.dbContext.GetTable<LDBComicChapterImage>();
                        if (tableComicChapterImages != null && tableComicChapterImages.Count() > 0)
                        {
                            var rowComicChapterImages = (from p in tableComicChapterImages where p.ComicId == comicId && p.BookId == bookId && p.PartId == chapterId select p).ToList<LDBComicChapterImage>();
                            if (rowComicChapterImages != null && rowComicChapterImages.Count > 0)
                            {
                                foreach (LDBComicChapterImage rowCCI in rowComicChapterImages)
                                {
                                    if (ContentDownloadStatus.已暂停.ToString().Equals(rowCCI.DownloadStatus))
                                    {
                                        rowCCI.DownloadStatus = ContentDownloadStatus.等待中.ToString();
                                        this.dbContext.SubmitChanges();
                                    }
                                }
                            }
                        }
                    }
                }
                result = true;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return result;
        }
        #endregion Comic'Chapter



        #region ******************************Comic******************************
        public void InsertComic(LDBComic comic)
        {
            try
            {
                mutex.WaitOne();
                if (comic == null)
                    return;

                LDBComic row = null;
                var table = this.dbContext.GetTable<LDBComic>();
                if (table != null && table.Count() > 0)
                {
                    row = table.Where(p => p.ComicId == comic.ComicId && p.BookId == comic.BookId).FirstOrDefault<LDBComic>();
                }
                if (row != null)
                {
                    if (!string.IsNullOrWhiteSpace(comic.ComicTitle))
                        row.ComicTitle = comic.ComicTitle;
                    if (!string.IsNullOrWhiteSpace(comic.CoverUrl))
                        row.CoverUrl = comic.CoverUrl;
                    if (!string.IsNullOrWhiteSpace(comic.DownloadStatus))
                        row.DownloadStatus = comic.DownloadStatus;
                }
                else
                {
                    this.dbContext.Comics.InsertOnSubmit(comic);
                }
                this.dbContext.SubmitChanges();
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }


        public ObservableCollection<LDBComic> GetAllComics()
        {
            try
            {
                mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComic>();
                if (table != null && table.Count() > 0)//无记录时，count()方法会报错            
                {
                    var list = table.ToList<LDBComic>();
                    if (list != null && list.Count > 0)
                    {
                        return new ObservableCollection<LDBComic>(list);
                    }
                }
            }
            catch (Exception err)
            {

            }
            finally
            {
                mutex.ReleaseMutex();
            }
            return null;
        }

        public LDBComic GetOneComicByDownloadStatus(ContentDownloadStatus status, int comicId = 0,int bookId=0)
        {
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComic>();
                if (table != null && table.Count() > 0)
                {
                    return table.Where(p => ((comicId <= 0 ? true : p.ComicId == comicId)) && (bookId <= 0 ? true : p.BookId == bookId) && p.DownloadStatus.Equals(status.ToString())).OrderBy(p => p.ComicId).FirstOrDefault<LDBComic>();
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return null;
        }

        public bool RemoveComicByComicId(int comicId,int bookId)
        {
            bool result = false;
            try
            {
                this.mutex.WaitOne();
                var table = this.dbContext.GetTable<LDBComic>();
                if (table != null && table.Count() > 0)
                {
                    var items = table.Where(p => p.ComicId == comicId && p.BookId == bookId).ToList<LDBComic>();
                    if (items != null && items.Count > 0)
                    {
                        this.dbContext.Comics.DeleteAllOnSubmit(items);
                        this.dbContext.SubmitChanges();
                    }
                }
                result = true;
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
            finally
            {
                this.mutex.ReleaseMutex();
            }
            return result;
        }
        #endregion Comic
    }
}
